package com.ea.eadp.nexus.portal.tests.forbid;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;

import com.ea.eadp.nexus.test.common.BrowserFactory;
import com.ea.eadp.nexus.test.common.SystemProperties;
import com.ea.eadp.nexus.test.common.TestUtil;
import com.ea.eadp.nexus.test.common.ApiClients.NucleusApi;
import com.ea.eadp.nexus.test.pageDefinition.Signin_PC;
import com.ea.eadp.nexus.test.pageDefinition.Signin_Web;
import com.ea.eadp.nexus.test.pageDefinition.Signup_PC;
import com.ea.eadp.nexus.test.pageDefinition.Signup_Web;
import com.ea.eadp.nexus.test.pageDefinition.console.CreateAccountPage;
import com.ea.eadp.nexus.test.pageDefinition.console.EnterAccountPage;
import com.ea.eadp.nexus.test.pageDefinition.console.SecureQuestionPage;
import com.ea.eadp.nexus.test.pageDefinition.console.TosPage;
import com.ea.eadp.nexus.test.pageDefinition.console.WelcomePage;
import com.ea.eadp.nexus.test.pageDefinition.gameconnect.GameConnectSigninPage;
import com.ea.eadp.test.shared.utility.IdentityBlackListHelper;

/**
 * Created by yimingcao on 9/3/2014.
 */
public class SecenarioProducer {
    @BeforeClass(alwaysRun = true)
    private void init() {
        //Initialize the chrome driver path from configuration file
        SystemProperties.instance();
    }

    private WebDriver getDriver() throws Exception {
        return BrowserFactory.createChromeWebDriver();
    }

    public String defaultPassword = "1234qwER";
    private String caseName;

    private IdentityBlackListHelper blackListHelper;

    public SecenarioProducer(String _caseName) throws Exception {
        String identityUri = System.getProperty("identity.client.uri");

        String regex = "http://(.+?)/(\\d)";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(identityUri);

        if (matcher.matches()) {
            String hostname = matcher.group(1);
            String version = matcher.group(2);
            String port = "80";

            if (hostname.contains(":")) {
                String[] xx = hostname.split(":");
                hostname = xx[0];
                port = xx[1];
            }

            System.setProperty("eaidpid.host.hostname", hostname);
            System.setProperty("eaidpid.host.version", version);
            System.setProperty("eaidpid.host.port", port);
        } else
        {
            throw new Exception("identity.client.uri?");
        }

        caseName = _caseName;
        blackListHelper = new IdentityBlackListHelper();
    }

    public void havingIpInClientIdSpecifiedBlackList(String ip, TestClientIDs clientId, Boolean ifTrue) throws Exception {
        if (ifTrue == true) blackListHelper.addBlackListItem(blackListHelper.createIPBlackListItem(ip, clientId.getClientId()));
    }

    public void havingIpInGlobalBlackList(String ip, Boolean ifTrue) throws Exception {
        if (ifTrue == true) blackListHelper.addBlackListItem(blackListHelper.createIPBlackListItem(ip, null));
    }

    public void havingIpInOtherClientIdSpecifiedBlackList(String ip, TestClientIDs clientId, Boolean ifTrue) throws Exception {
        if (ifTrue == true) {
            if (clientId.equals(TestClientIDs.DEFAULT_SMOKE_CLIENT))
            {
                blackListHelper.addBlackListItem(blackListHelper.createIPBlackListItem(ip, TestClientIDs.MOBILE_CLIENT.getClientId()));
            }
            else
            {
                blackListHelper.addBlackListItem(blackListHelper.createIPBlackListItem(ip, TestClientIDs.DEFAULT_SMOKE_CLIENT.getClientId()));
            }
        }
    }

    public void cleanUpBlackListForOneIP(String ip) throws Exception {
        blackListHelper.removeIpFromEveryBlackList(ip, TestClientIDs.DEFAULT_SMOKE_CLIENT.getClientId(), TestClientIDs.MOBILE_CLIENT.getClientId(), TestClientIDs.CONSOLE2_CLIENT.getClientId());
    }

    public LoginResult login(TestDisplayNames display, String userName, String passWord) throws Exception {
        switch (display)
        {
            case WEB_LOGIN:
                return loginWeb_Login(userName, passWord);
            case PC_LOGIN:
                return loginPc_Login(userName, passWord);
            case MOBILEGAME_LOGIN:
                return loginMobileGame_Login(userName, passWord);
            case CONSOLE2_WELCOME:
                return loginConsole2_Login(userName, passWord);
            case GCON_LOGIN:
                return loginGcon_Login(userName, passWord);
            default:
                return null;
        }
    }

    public RegisterResult register(TestDisplayNames display) throws Exception {
        switch(display)
        {
            case WEB_CREATE:
                return registerWeb_Create();
            case PC_CREATE:
                return registerPc_Create();
            case CONSOLE2_WELCOME:
                return registerConsole2_Welcome();
            default:
                return null;
        }
    }

    public String havingAOriginUser() throws Exception {
        String email = TestUtil.getRandomEmail();
        String pidUrl = NucleusApi.instance().postPid(email, defaultPassword);
        Long pidID = TestUtil.getPidID(pidUrl);
        String originId = TestUtil.getRandomOriginId();
        NucleusApi.instance().postPersona(pidID, originId);
        NucleusApi.instance().postSecurityQA(pidID);

        return email;
    }

    public LoginResult loginWeb_Login(String userName, String passWord) throws Exception {
        WebDriver driver = getDriver();
        Signin_Web signin_web = new Signin_Web(driver);
        signin_web.navigate();
        signin_web.setSigninEmail(userName);
        signin_web.setSigninPassword(passWord);
        try {
            signin_web.clickToSigninComplete();
            if (TestUtil.getCurrentUrl(driver).contains("?code=")) {
                return new LoginResult();
            } else
            {
                return new LoginResult(LoginStatus.Failed, null, signin_web.getError());
            }
        } catch (Exception ex) {
            return new LoginResult(LoginStatus.Failed, ex, "");
        }
        finally {
            driver.manage().deleteAllCookies();
            driver.quit();
        }
    }

    public RegisterResult registerWeb_Create() throws Exception {
        WebDriver driver = getDriver();
        Signup_Web signup_web = new Signup_Web(driver);
        try {
            signup_web.navigate();
            signup_web.setSignupEmail(TestUtil.getRandomEmail());
            signup_web.clickToSignupBasicS1();
            signup_web.setOriginID(TestUtil.getRandomOriginId());
            signup_web.setSignupPassword(defaultPassword);
            signup_web.setConfirmPassword(defaultPassword);
            signup_web.setSecurityQuestion(TestUtil.getRandomSecurityQuestion());
            signup_web.setSecurityAnswer(TestUtil.getRandomSecurityAnswer());
            signup_web.setDobMonth(TestUtil.getRandomMonth());
            signup_web.setDobDay(TestUtil.getRandomDayOfMonth());
            signup_web.setDobYear(TestUtil.getRandomPastYear());
            signup_web.setRegisterCountry("US");
            signup_web.setCaptcha(TestUtil.getRandomString());
            signup_web.checkboxContactMe(true);
            signup_web.checkboxShareInfo(true);
            signup_web.checkboxReadAccept(true);
            signup_web.clickToSignupBasicS2();
            signup_web.setFirstName(TestUtil.getRandomString("first", 1000));
            signup_web.setLastName(TestUtil.getRandomString("last", 1000));
            signup_web.clickToSignupBasicS3();
            signup_web.clickSignup();
            return new RegisterResult();
        } catch (Exception e) {
            TestUtil.getScreenshot(driver, SecenarioProducer.class, caseName);
            RegisterResult registerResult = new RegisterResult();
            registerResult.registerStatus = RegisterStatus.Failed;
            registerResult.ex = e;
            registerResult.error = signup_web.getErrorMessageByXPath("//div[@id='splash-error']/div[1]/div[1]");
            return registerResult;
        } finally {
            driver.manage().deleteAllCookies();
            driver.quit();
        }
    }

    public RegisterResult registerPc_Create() throws Exception {
        WebDriver driver = getDriver();
        Signup_PC signup_pc = new Signup_PC(driver);
        try {
            driver.manage().window().maximize();
            signup_pc.navigate();
            signup_pc.setDobMonth(TestUtil.getRandomMonth());
            signup_pc.setDobDay(TestUtil.getRandomDayOfMonth());
            signup_pc.setDobYear(TestUtil.getRandomPastYear());
            signup_pc.setRegisterCountry("CA");
            signup_pc.clickToSignupBasicS1();
            String originId = TestUtil.getRandomOriginId();
            signup_pc.setOriginID(originId);
            String email = TestUtil.getRandomEmail();
            signup_pc.setSignupEmail(email);
            signup_pc.setSignupPassword(defaultPassword);
            signup_pc.setConfirmPassword(defaultPassword);
            signup_pc.setSecurityQuestion(TestUtil.getRandomSecurityQuestion());
            signup_pc.setSecurityAnswer(TestUtil.getRandomSecurityAnswer());
            signup_pc.setVisibility(TestUtil.getRandomVisibility());
            signup_pc.checkboxSearchByEmail(true);
            signup_pc.checkboxSearchByXboxId(false);
            signup_pc.checkboxSearchByPSNId(false);
            signup_pc.setCaptcha(TestUtil.getRandomString());
            Assert.assertFalse(driver.findElement(By.id("contactMe")).isSelected());
            Assert.assertFalse(driver.findElement(By.id("shareInfo")).isSelected());
            signup_pc.checkboxContactMe(true);
            signup_pc.checkboxShareInfo(true);
            signup_pc.checkboxReadAccept(true);
            TestUtil.sleep(1);
            ((JavascriptExecutor)driver).executeScript("$(\"#submit-btn\").click()");
            TestUtil.sleep(2);
            signup_pc.setFirstName(TestUtil.getRandomString("first", 1000));
            signup_pc.setLastName(TestUtil.getRandomString("last", 1000));
            signup_pc.clickToSignupComplete();
            return new RegisterResult();
        } catch (Exception ex)
        {
            TestUtil.getScreenshot(driver, SecenarioProducer.class, caseName);
            RegisterResult registerResult = new RegisterResult();
            registerResult.registerStatus = RegisterStatus.Failed;
            registerResult.ex = ex;
            registerResult.error = "";
            return registerResult;
        } finally {
            driver.manage().deleteAllCookies();
            driver.quit();
        }
    }

    public RegisterResult registerConsole2_Welcome() throws Exception {
        WebDriver driver = getDriver();
        try {
            WelcomePage welcomePage = new WelcomePage(driver);
            welcomePage.navigate(TestUtil.getConsoleConnectUrl(TestDisplayNames.CONSOLE2_WELCOME.getClientId().getClientId(), "basic.identity"));
            welcomePage.waitPageLoadCompleted();
            welcomePage.selectRegister();

            TosPage tosPage = new TosPage(driver);
            tosPage.waitPageLoadCompleted();
            tosPage.acceptTOS();

            EnterAccountPage emailPage = new EnterAccountPage(driver);
            emailPage.waitPageLoadCompleted();
            emailPage.startSignup();
            String email = TestUtil.getRandomEmail();
            emailPage.fillEmail(email);
            emailPage.fillPassword(defaultPassword);
            emailPage.fillConfirmPassword(defaultPassword);
            String originId = TestUtil.getRandomOriginId();
            emailPage.fillOriginId(originId);

            SecureQuestionPage sqPage = new SecureQuestionPage(driver);
            sqPage.waitPageLoadCompleted();
            sqPage.selectSecurityQuestion(5);
            sqPage.selectSecurityQuestion(3);
            sqPage.selectSecurityQuestion(-4);
            sqPage.fillSqAnswer(1, TestUtil.getRandomSecurityAnswer());
            sqPage.selectSecurityQuestion(1);
            sqPage.fillSqAnswer(2, TestUtil.getRandomSecurityAnswer());
            sqPage.selectSecurityQuestion(1);
            sqPage.fillSqAnswer(3, TestUtil.getRandomSecurityAnswer());
            CreateAccountPage createAccountPage = new CreateAccountPage(driver);
            createAccountPage.waitPageLoadCompleted();
            createAccountPage.clickContinue();

            //todo
            TestUtil.sleep(5);

            String url = TestUtil.getCurrentUrl(driver);

            if (url.matches(".*\\?code=.*")) {
                return new RegisterResult();
            } else {
                RegisterResult registerResult = new RegisterResult();
                registerResult.registerStatus = RegisterStatus.Failed;
                registerResult.error = createAccountPage.getErrorMessageTitle();
                return registerResult;
            }
        } catch (Exception e) {
            RegisterResult registerResult = new RegisterResult();
            registerResult.registerStatus = RegisterStatus.Failed;
            registerResult.ex = e;
            registerResult.error = e.toString();
        } finally {
            driver.manage().deleteAllCookies();
            driver.quit();
        }

        return null;
    }

    public LoginResult loginPc_Login(String userName, String passWord) throws Exception {
        WebDriver driver = getDriver();
        Signin_PC signin_pc = new Signin_PC(driver);
        signin_pc.navigate();
        signin_pc.setSigninEmail(userName);
        signin_pc.setSigninPassword(passWord);
        try {
            signin_pc.clickToSigninComplete();
            return new LoginResult();
        } catch (Exception ex)
        {
            TestUtil.getScreenshot(driver, SecenarioProducer.class, caseName);
            return new LoginResult(LoginStatus.Failed, ex, signin_pc.getError());
        }
        finally {
            driver.manage().deleteAllCookies();
            driver.quit();
        }
    }

    public LoginResult loginMobileGame_Login(String userName, String passWord) throws Exception {
        WebDriver driver = getDriver();
        com.ea.eadp.nexus.test.pageDefinition.mobile.LoginPage loginPage = new com.ea.eadp.nexus.test.pageDefinition.mobile.LoginPage(driver);
        loginPage.navigate(TestUtil.getMobileConnectUrl(TestClientIDs.MOBILE_CLIENT.getClientId()));
        loginPage.waitPageLoadCompleted();
        loginPage.enterEmail(userName);
        loginPage.enterPassword(passWord);
        loginPage.login();

        //todo
        TestUtil.sleep(10);
        String content = driver.getPageSource();

        try {
            if (content.matches(".*\"code\":.*")) {
                return new LoginResult();
            } else {
                TestUtil.getScreenshot(driver, SecenarioProducer.class, caseName);
                return new LoginResult(LoginStatus.Failed, null, loginPage.getLoginResponse());
            }
        } finally {
            driver.manage().deleteAllCookies();
            driver.quit();
        }
    }

    public LoginResult loginConsole2_Login(String userName, String passWord) throws Exception {
        WebDriver driver = getDriver();
        com.ea.eadp.nexus.test.pageDefinition.newconsole.WelcomePage welcomePage = new com.ea.eadp.nexus.test.pageDefinition.newconsole.WelcomePage(driver);
        welcomePage.navigate(TestUtil.getConsole2ConnectUrl(TestClientIDs.CONSOLE2_CLIENT.getClientId(), null));
        welcomePage.waitPageLoadCompleted();
        welcomePage.acceptTOS();

        com.ea.eadp.nexus.test.pageDefinition.newconsole.OriginAccountPage originAccountPage = new com.ea.eadp.nexus.test.pageDefinition.newconsole.OriginAccountPage(driver);
        originAccountPage.waitPageLoadCompleted();
        originAccountPage.enterEmail(userName);

        com.ea.eadp.nexus.test.pageDefinition.newconsole.WelcomeBackPage welcomeBackPage = new com.ea.eadp.nexus.test.pageDefinition.newconsole.WelcomeBackPage(driver);
        welcomeBackPage.waitPageLoadCompleted();

        welcomeBackPage.enterPassword(passWord);

        //todo
        TestUtil.sleep(5);

     try {
            if (TestUtil.getCurrentUrl(driver).matches(".*\\?code=.*")) {
                return new LoginResult();
            } else {
                TestUtil.getScreenshot(driver, SecenarioProducer.class, caseName);
                return new LoginResult(LoginStatus.Failed, null, welcomeBackPage.getErrorMessageTitle());
            }
        } finally {
            driver.manage().deleteAllCookies();
            driver.quit();
        }
    }

    public LoginResult loginGcon_Login(String userName, String passWord) throws Exception {
        WebDriver driver = getDriver();
        try {
            GameConnectSigninPage gameConnectSigninPage= new GameConnectSigninPage(driver);
            gameConnectSigninPage.navigate(TestUtil.getGameConnectSigninUrl("Integration-Test", "testRetailer"));
            gameConnectSigninPage.setEmail(userName);
            gameConnectSigninPage.setPassword(passWord);
            gameConnectSigninPage.clickToSignIn();
            driver.findElement(By.xpath("//*[contains(.,'" + "Account Linked Successfully" + "')]"));
            }catch (NoSuchElementException e){
                return new LoginResult(LoginStatus.Failed, null,"");
            }finally {
            driver.manage().deleteAllCookies();
            driver.quit();
        }
        return new LoginResult(LoginStatus.Success, null,"");
    }

    public class LoginResult
    {
        public LoginStatus loginStatus;
        public Exception ex;
        public String error;

        public LoginResult()
        {
            loginStatus = LoginStatus.Success;
            ex = null;
            error = null;
        }

        public LoginResult(LoginStatus _loginStatus, Exception _ex, String _error)
        {
            loginStatus = _loginStatus;
            ex = _ex;
            error = _error;
        }

        @Override
        public String toString()
        {
            return String.format("LoginStatus: %s, Exception: %s, Error: %s", loginStatus.toString(), ex.toString(), error);
        }
    }

    public class RegisterResult
    {
        public RegisterStatus registerStatus;
        public Exception ex;
        public String error;

        public RegisterResult()
        {
            registerStatus = RegisterStatus.Success;
            ex = null;
            error = null;
        }

        public RegisterResult(RegisterStatus _registerStatus, Exception _ex, String _error)
        {
            registerStatus = _registerStatus;
            ex = _ex;
            error = _error;
        }
    }

    public enum LoginStatus
    {
        Failed,
        Success
    }

    public enum RegisterStatus
    {
        Failed,
        Success
    }

    public enum TestClientIDs
    {
        DEFAULT_SMOKE_CLIENT("smoke_client"),
        MOBILE_CLIENT("mobile-test-client"),
        CONSOLE2_CLIENT("newconsole-test-client2");

        private TestClientIDs(String _clientId) {
            clientId = _clientId;
        }

        public String toString() {
            return clientId;
        }

        public String getClientId()
        {
            return clientId;
        }

        private String clientId;
    }

    public enum TestDisplayNames
    {
        WEB_LOGIN("web/login", TestClientIDs.DEFAULT_SMOKE_CLIENT, "We're sorry, but we're having some technical difficulties. Please try again later."),
        WEB_CREATE("web/create", TestClientIDs.DEFAULT_SMOKE_CLIENT, null),
        PC_LOGIN("pc/login", TestClientIDs.DEFAULT_SMOKE_CLIENT, "We're sorry, but we're having some technical difficulties. Please try again later."),
        PC_CREATE("pc/create", TestClientIDs.DEFAULT_SMOKE_CLIENT, null),
        MOBILEGAME_LOGIN("mobilegame/login", TestClientIDs.MOBILE_CLIENT, "Sorry! We are experiencing some technical difficulties. Please try again later."),
        CONSOLE2_WELCOME("console2/welcome", TestClientIDs.CONSOLE2_CLIENT, "Please try again later."),
        GCON_LOGIN("gcon/login", TestClientIDs.DEFAULT_SMOKE_CLIENT, ""),
        GCON_CREATE("gcon/create", TestClientIDs.DEFAULT_SMOKE_CLIENT, "");

        private TestDisplayNames(String _displayName, TestClientIDs _clientId, String _errorMessage)
        {
            displayName = _displayName;
            testClientIDs = _clientId;
            errorMessageIfBlockedByBlackList = _errorMessage;
        }

        public String getDisplayName()
        {
            return displayName;
        }

        public TestClientIDs getClientId()
        {
            return testClientIDs;
        }

        public String getErrorMessageIfBlockedByBlackList()
        {
            return errorMessageIfBlockedByBlackList;
        }

        private String displayName;
        private TestClientIDs testClientIDs;
        private String errorMessageIfBlockedByBlackList;
    }
}


